package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.help.FormDataHelp;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.ProductFieldPojo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.costadjust.dto.CostAdjustDeleteBatchDTO;
import com.xbongbong.pro.costadjust.dto.CostAdjustEditAttrUpdateDTO;
import com.xbongbong.pro.costadjust.dto.CostAdjustUpdateBatchDTO;
import com.xbongbong.pro.costadjust.dto.CostAdjustUpdateDTO;
import com.xbongbong.pro.costadjust.vo.CostAdjustDeleteBatchVO;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.OutstockErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.form.pojo.dto.ChildProductDTO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainInLinkItemDTO;
import com.xbongbong.pro.product.pojo.dto.CostRecalculationDTO;
import com.xbongbong.pro.product.pojo.dto.PagingProductDTO;
import com.xbongbong.pro.product.pojo.vo.DetailProductVO;
import com.xbongbong.pro.product.pojo.vo.PagingProductVO;
import com.xbongbong.pro.rabbitmq.producer.CostRecalculationProducer;
import com.xbongbong.saas.analytical.impl.CostAdjustValidateAnalyticalServiceImpl;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.BatchFlowBillUpdateEntity;
import com.xbongbong.saas.domain.entity.CostAdjustProductEntity;
import com.xbongbong.saas.domain.entity.ProductStockEntity;
import com.xbongbong.saas.domain.entity.ProductStockUpdateEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.SettleAccountsEntity;
import com.xbongbong.saas.domain.entity.StockFlowBillUpdateEntity;
import com.xbongbong.saas.domain.entity.ext.CostAdjustEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.WarehouseEntityExt;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.StockTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.CostAdjustEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.WarehouseEnum;
import com.xbongbong.saas.enums.product.CostAdjustProductEnum;
import com.xbongbong.saas.help.BatchKeyHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.help.SaasDeleteHelp;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.model.CostAdjustModel;
import com.xbongbong.saas.model.CostAdjustProductModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductStockModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.SettleAccountsModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.service.CostAdjustService;
import com.xbongbong.saas.service.ProductService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.ProductHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author WuHB
 * @date 2021/11/23 17:01
 */
@Service("costAdjustService")
public class CostAdjustServiceImpl implements CostAdjustService {

    private static final Logger LOG = LoggerFactory.getLogger(CostAdjustServiceImpl.class);

    @Resource
    private CostAdjustModel costAdjustModel;

    @Resource
    private ProductStockModel productStockModel;

    @Resource
    private SettleAccountsModel settleAccountsModel;

    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;

    @Resource
    private CostAdjustProductModel costAdjustProductModel;

    @Resource
    private ProductWarehouseModel productWarehouseModel;

    @Resource
    private ProductService productService;

    @Resource
    private PaasEsModel paasEsModel;

    @Resource
    private ProductHelp productHelp;

    @Resource
    private SaasFormHelp saasFormHelp;

    @Resource
    private MongoLogHelp mongoLogHelp;

    @Resource
    private LogHelp logHelp;

    @Resource
    private ImportHelper importHelper;

    @Resource
    private ProductModel productModel;

    @Resource
    private WarehouseModel warehouseModel;

    @Resource
    private RelativeProductHelp relativeProductHelp;

    @Resource
    private CostRecalculationProducer costRecalculationProducer;

    @Resource
    private CostAdjustValidateAnalyticalServiceImpl costAdjustValidateAnalyticalService;

    @Resource
    private SaasDeleteHelp saasDeleteHelp;

    @Resource
    private SaasUpdateHelp saasUpdateHelp;

    @Resource
    private FormDataHelp formDataHelp;
    @Resource
    private LogHandleHelp logHandleHelp;

    /**
     * 成本调整单保存前saas特殊校验
     *
     * @param validateDataDTO saas特殊校验数据入参
     * @throws XbbException 业务异常
     */
    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        costAdjustValidateAnalyticalService.beforeSave(validateDataDTO);
    }

    /**
     * 成本调整单保存后逻辑
     *
     * @param saasFormSaveDTO saas保存数据
     * @throws XbbException 业务异常
     */
    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        if (saasFormSaveDTO.getIsNew()) {
            JSONObject data = saasFormSaveDTO.getNewData();
            String corpid = saasFormSaveDTO.getCorpid();
            JSONArray productJsonArray = data.getJSONArray(CostAdjustEnum.PRODUCT.getAttr());
            String productStr = productJsonArray.toJSONString();
            PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
            Long costAdjustId = newEntity.getId();
            Long formId = newEntity.getFormId();
            saveProduct(productJsonArray, corpid, costAdjustId, formId, false);
            // 序列号入库
            //productSerialService.saveSerial(saasFormSaveDTO, productStr);
            SaasFormSaveDTO saasFormSaveDTOCost = new SaasFormSaveDTO();
            saasFormSaveDTOCost.setCorpid(saasFormSaveDTO.getCorpid());
            saasFormSaveDTOCost.setBusinessType(saasFormSaveDTO.getBusinessType());
            saasFormSaveDTOCost.setNewData(saasFormSaveDTO.getNewData());
            saasFormSaveDTOCost.setNewPaasFormDataEntity(saasFormSaveDTO.getNewPaasFormDataEntity());
            CostRecalculationDTO costRecalculationDTO = new CostRecalculationDTO();
            costRecalculationDTO.setType(StockTypeEnum.ADJUST_STOCK.getCode());
            costRecalculationDTO.setData(data);
            costRecalculationDTO.setStockId(costAdjustId);
            costRecalculationDTO.setCorpid(corpid);
            costRecalculationDTO.setMark(BasicConstant.ONE);
            costRecalculationDTO.setIsWorkFlow(BasicConstant.ONE);
            costRecalculationDTO.setSaasFormSaveDTO(saasFormSaveDTOCost);
            //将流水放至重算方法中生成，保证处理的先后顺序
            /*stockFlowBillService.caculateStockModification4Save(saasFormSaveDTO);
            batchFlowBillService.batchFlowModification4Save(saasFormSaveDTO);*/
            costRecalculationProducer.sendMessage(costRecalculationDTO);
        }
    }

    /**
     * 成本调整单产品保存
     *
     * @param productArray 产品数组
     * @param corpid       公司id
     * @param costAdjustId 对应入库单的id
     * @param formId       表单ID
     * @param isWorkflow   是否工作流
     * @throws XbbException 业务异常
     */
    @Override
    public void saveProduct(JSONArray productArray, String corpid, Long costAdjustId, Long formId, boolean isWorkflow) throws XbbException {
        //新增
        List<CostAdjustProductEntity> addCostAdjustProductEntityList = new ArrayList<>();
        // 获取调整单产品信息
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid, productArray);
        // 获取调整单产品所有仓库信息
        Map<Long, List<ProductWarehouseEntity>> productAllWarehouseMap = this.findProductAllWarehouse(corpid, productArray);
        // 获取调整单产品所有批次信息
        Map<Long, List<ProductStockEntity>> productAllBatchMap = this.findProductAllBatch(corpid, productArray);
        // 需要更新的批次信息
        List<ProductStockUpdateEntity> updateStockList = new ArrayList<>();
        // 需要更新的仓库信息
        List<ProductWarehouseEntity> updateWarehouseList = new ArrayList<>();
        // 需要跟新的产品信息
        Map<Long, ProductStockUpdateEntity> updateProductMap = new HashMap<>();
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            jsonObject.put(SelectProductEnum.NUM.getAttr(), 0);
            // 是否开启了批次
            Integer enableBatchShelfLife = jsonObject.getInteger(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr());
            // 移除序列号相关数据，不存入关联产品数据中
            ProductFieldPojo productFieldPojo = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), corpid);
            // 产品ID
            Long productId = jsonObject.getLong(CostAdjustProductEnum.PRODUCT.getAttr());
            // 仓库ID
            Long warehouseId = this.getWarehouseId(jsonObject.getJSONArray(CostAdjustProductEnum.WAREHOUSE.getAttr()));
            // 批次Key
            String batchKey = BatchKeyHelp.getBatchKey(productId, warehouseId, jsonObject.getString(CostAdjustProductEnum.BATCH.getAttr()),
                    jsonObject.getLong(CostAdjustProductEnum.PRODUCE_DATE.getAttr()), getGuaranteePeriod(jsonObject.getLong(CostAdjustProductEnum.GUARANTEE_PERIOD.getAttr())));
            // 产品信息
            JSONObject productData = productMap.get(productId).getData();
            // 调整金额
            BigDecimal adjustAmount = jsonObject.getBigDecimal(CostAdjustProductEnum.ADJUST_AMOUNT.getAttr());
            // 获取批次总成本
            List<ProductStockEntity> productStockEntityList = productAllBatchMap.get(productId);
            BigDecimal totalBatchAmount = this.getBatchTotalCost(productStockEntityList, updateStockList, jsonObject, adjustAmount);
            // 获取仓库总成本
            List<ProductWarehouseEntity> productWarehouseEntitieList = productAllWarehouseMap.get(productId);
            if (CollectionsUtil.isEmpty(productWarehouseEntitieList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, MessageConstant.WAREHOUSE_INFO_NOT_EMPTY, productId);
            }
            BigDecimal totalWarehouseAmount = this.getWarehouseTotalCost(productWarehouseEntitieList, updateWarehouseList, jsonObject, productId, warehouseId, totalBatchAmount, adjustAmount);
            // 计算出产品的总成本是多少并放入待更新集合
            BigDecimal productStock = productData.getBigDecimal(ProductEnum.STOCK.getAttr());
//            BigDecimal productCost = totalWarehouseAmount.divide(productStock, 7, RoundingMode.HALF_DOWN);
            if (Objects.isNull(adjustAmount)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
            }
            ProductStockUpdateEntity productStockUpdateEntity = new ProductStockUpdateEntity(productId,  Double.valueOf(adjustAmount.toString()));
            if (updateProductMap.containsKey(productId)) {
                ProductStockUpdateEntity updateEntity = updateProductMap.get(productId);
                Double cost = updateEntity.getCost();
                updateEntity.setCost(Double.valueOf(BigDecimal.valueOf(cost).add(adjustAmount).toString()));
            } else {
                updateProductMap.put(productId, productStockUpdateEntity);
            }
            // 获取调整单实体
            CostAdjustProductEntity costAdjustProductEntity = this.getAdjustEntity(adjustAmount, batchKey, productData, productId, warehouseId, productStockEntityList, productWarehouseEntitieList);
            costAdjustProductEntity.setCorpid(corpid);
            costAdjustProductEntity.setFormId(formId);
            costAdjustProductEntity.setCostAdjustId(costAdjustId);
            costAdjustProductEntity.setProductId(productId);
            costAdjustProductEntity.setWarehouseId(warehouseId);
            costAdjustProductEntity.setSort(i);
            costAdjustProductEntity.setCostAdjustAmount(adjustAmount);
            String unitId = jsonObject.getString(CostAdjustProductEnum.BASIC_UNIT.getAttr());
            costAdjustProductEntity.setProductUnit(unitId);
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.nonNull(enableMultiUnit) && Objects.equals(enableMultiUnit, 1)) {
                List<MultiUnitItemPoJo> multiItems = productFieldPojo.getMultiItems();
                MultiUnitItemPoJo multiUnitItemPoJo = null;
                if (CollectionUtils.isNotEmpty(multiItems)) {
                    multiUnitItemPoJo = multiItems.stream().filter(item -> Objects.equals(unitId, String.valueOf(item.getValue()))).findFirst().orElse(null);
                }
                if (Objects.nonNull(multiUnitItemPoJo)) {
                    costAdjustProductEntity.setBusinessUnit(multiUnitItemPoJo.getBaseValue());
                    List<UnitItemPoJo> itemDataPoJoList = multiUnitItemPoJo.getItemDataPoJoList();
                    MultiUnitItemPoJo finalMultiUnitItemPoJo = multiUnitItemPoJo;
                    UnitItemPoJo unitItemPoJo = itemDataPoJoList.stream().filter(item -> Objects.equals(finalMultiUnitItemPoJo.getBaseValue(), item.getValue())).findFirst().orElse(new UnitItemPoJo());
                    costAdjustProductEntity.setRate(unitItemPoJo.getRate());
                    costAdjustProductEntity.setGroupId(multiUnitItemPoJo.getValue());
                    costAdjustProductEntity.setProductUnit(String.valueOf(multiUnitItemPoJo.getBaseValue()));
                }
            } else {
                jsonObject.put(CostAdjustProductEnum.BASIC_UNIT.getAttr(), productData.getString(ProductEnum.UNIT.getAttr()));
            }
            jsonObject.put(CostAdjustProductEnum.STOCK.getAttr(), costAdjustProductEntity.getInventoryNumber());
            jsonObject.put(CostAdjustProductEnum.TOTAL_COST.getAttr(), costAdjustProductEntity.getTotalCost());
            costAdjustProductEntity.setData(jsonObject);
            addCostAdjustProductEntityList.add(costAdjustProductEntity);
        }
        if (CollectionsUtil.isNotEmpty(addCostAdjustProductEntityList) && Objects.nonNull(costAdjustId)) {
            costAdjustProductModel.insertBatch(addCostAdjustProductEntityList);
        }
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            jsonObject.put(BusinessConstant.PRODUCT_SUB_ID, addCostAdjustProductEntityList.get(i).getId());
            jsonObject.put(BusinessConstant.REF_PRODUCT_ID, addCostAdjustProductEntityList.get(i).getId());
        }
        // 修改成本
        if (!isWorkflow) {
            if (CollectionsUtil.isNotEmpty(updateStockList)) {
                Set<String> batchkeySet = updateStockList.stream().map(ProductStockUpdateEntity::getKey).collect(Collectors.toSet());
                productStockModel.updateStockDB(batchkeySet, updateStockList, corpid);
            }
            productWarehouseModel.updateStockBatch(updateWarehouseList, corpid);
            productService.updateProductStock(updateProductMap, corpid);
        }
    }

    @Override
    public PagingProductVO getPagingProduct(PagingProductDTO pagingProductDTO) throws XbbException {
        PagingProductVO pagingProductVO = new PagingProductVO();
        String corpid = pagingProductDTO.getCorpid();
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, pagingProductDTO.getCorpid());
        modelMap.put("costAdjustId", pagingProductDTO.getDataId());
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put(ParameterConstant.PAGE, pagingProductDTO.getPage());
        modelMap.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
        PageHelper pageHelper = PageHelperUtil.getPageHelper(modelMap, costAdjustProductModel, pagingProductDTO.getPageSize());
        List<CostAdjustProductEntity> productEntityList = (List<CostAdjustProductEntity>) PageHelperUtil.getEntityList(modelMap, pageHelper, costAdjustProductModel);
        if (pagingProductDTO.getUpdateDataTypeEnum().isDetail()) {
            DetailProductVO detailProductVO = formatProduct4DetailShow(productEntityList, pagingProductDTO);
            JSONArray productDataArr = detailProductVO.getProductDataArr();
            for (int i = 0; i < productDataArr.size(); i++) {
                JSONObject jsonObject = productDataArr.getJSONObject(i);
                String unitId = jsonObject.getString(CostAdjustProductEnum.BASIC_UNIT.getAttr());
                Map<String, String> unitMap4Product = this.getUnitMap4Product(corpid, jsonObject.getLong(SelectProductEnum.UNIT_GROUP.getAttr()));
                jsonObject.put(CostAdjustProductEnum.BASIC_UNIT.getAttr(), unitMap4Product.getOrDefault(unitId, unitId));
                jsonObject.put(SelectProductEnum.BUSINESS_UNIT.getAttr(), unitMap4Product.getOrDefault(unitId, unitId));
                jsonObject.put(CostAdjustProductEnum.STOCK.getAttr(), jsonObject.getBigDecimal(CostAdjustProductEnum.STOCK.getAttr()));
                Object shelfLifeDays = jsonObject.get(ProductConstant.Shelf_Life_Days);
                // 保质期转换
                if (Objects.nonNull(shelfLifeDays) && Objects.equals(BasicConstant.ONE,Integer.valueOf(shelfLifeDays.toString()))){
                    jsonObject.put(CostAdjustProductEnum.GUARANTEE_PERIOD.getAttr(),Arith.div(jsonObject.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()),86400D ));
                }
            }
            pagingProductVO.setProductDataArr(detailProductVO.getProductDataArr());
        }
        pagingProductVO.setPageHelper(pageHelper);
        return pagingProductVO;
    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        // 逻辑改为仅新建进行入库单保存后逻辑：产品保存，库存更新，上游单据更新
        JSONObject data = saasFormSaveDTO.getNewData();
        String corpid = saasFormSaveDTO.getCorpid();
        JSONArray productJsonArray = data.getJSONArray(CostAdjustEnum.PRODUCT.getAttr());
        PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long costAdjustId = newEntity.getId();
        Long formId = saasFormSaveDTO.getNewPaasFormDataEntity().getFormId();
        saveProduct(productJsonArray, corpid, costAdjustId, formId, true);
    }

    @Override
    public CostAdjustDeleteBatchVO deleteBatch(CostAdjustDeleteBatchDTO costAdjustDeleteBatchDTO) throws XbbException {
        // 公司ID
        String corpid = costAdjustDeleteBatchDTO.getCorpid();
        // 删除判断
        CostAdjustEntityExt costAdjustEntityExt = this.deletecheck(costAdjustDeleteBatchDTO);
        Long dataId = costAdjustDeleteBatchDTO.getDataIdList().get(0);

        // 查询调整单单
        Map<String, Object> param = BeanUtil.convertBean2Map(costAdjustDeleteBatchDTO, true);
        param.put("del", 0);
        param.put("ids", costAdjustDeleteBatchDTO.getDataIdList());
        List<CostAdjustEntityExt> costAdjustEntityExtList = costAdjustModel.findEntitys(param);
        if (Objects.isNull(costAdjustEntityExtList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        List<Long> adjustIdList = costAdjustEntityExtList.stream().map(CostAdjustEntityExt::getId).collect(Collectors.toList());
        List<CostAdjustProductEntity> costAdjustProductList = costAdjustProductModel.getProductsByAdjustIdIn(corpid, adjustIdList);
        //查询编号
        Map<Long, String> adjustIdAndno= new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for(CostAdjustEntityExt entityExt : costAdjustEntityExtList){
            Long instockId = entityExt.getId();
            String sheetNo = entityExt.getSerialNo();
            adjustIdAndno.put(instockId, sheetNo);
        }
        //批次序列号校验
        Set<Long> disableBatchProducts = saasDeleteHelp.checkDocumentDelete(corpid, costAdjustProductList, adjustIdAndno);
        Map<Long, Long> timeMap = new HashMap<>(costAdjustEntityExtList.size());
        costAdjustEntityExtList.forEach(item -> {
            timeMap.put(item.getId(), item.getData().getLong(InstockEnum.TIME.getAttr()));
        });
        List<StockFlowBillUpdateEntity> stockFlowBillUpdateList = new ArrayList<>();
        List<BatchFlowBillUpdateEntity> batchFlowBillUpdateEntityList = new ArrayList<>();
        Map<Long, ProductStockUpdateEntity> updateProductMap = new HashMap<>();
        JSONArray productArray = new JSONArray();
        for (CostAdjustProductEntity item : costAdjustProductList) {
            StockFlowBillUpdateEntity stockFlowBillUpdateEntity = new StockFlowBillUpdateEntity(item.getProductId() + "_" + item.getWarehouseId(), 0D, Arith.sub(0D,item.getCostAdjustAmount().doubleValue()), timeMap.get(item.getCostAdjustId()), DateTimeUtil.getInt(), item.getCostAdjustId());
            stockFlowBillUpdateList.add(stockFlowBillUpdateEntity);
            if (StringUtil.isNotEmpty(item.getBatch()) && !disableBatchProducts.contains(item.getParentId())) {
                BatchFlowBillUpdateEntity batchFlowBillUpdateEntity = new BatchFlowBillUpdateEntity(item.getProductId() + "_" + item.getWarehouseId() + "_" + item.getBatch() + "_" + item.getProduceDate() + "_" + item.getGuaranteePeriod(), 0D, Arith.sub(0D,item.getCostAdjustAmount().doubleValue()), timeMap.get(item.getCostAdjustId()), DateTimeUtil.getInt(), item.getCostAdjustId());
                batchFlowBillUpdateEntityList.add(batchFlowBillUpdateEntity);
            }
            Long productId = item.getProductId();
            BigDecimal costAdjustAmount = item.getCostAdjustAmount();
            if (Objects.isNull(costAdjustAmount)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
            }
            ProductStockUpdateEntity productStockUpdateEntity = new ProductStockUpdateEntity(item.getProductId(),  Double.valueOf(item.getCostAdjustAmount().toString()));
            if (updateProductMap.containsKey(productId)) {
                ProductStockUpdateEntity updateEntity = updateProductMap.get(productId);
                Double cost = updateEntity.getCost();
                updateEntity.setCost(Double.valueOf(BigDecimal.valueOf(cost).add(item.getCostAdjustAmount()).toString()));
            } else {
                updateProductMap.put(productId, productStockUpdateEntity);
            }
            JSONObject data = item.getData();
            BigDecimal adjustAmount = data.getBigDecimal(CostAdjustProductEnum.ADJUST_AMOUNT.getAttr());
            data.put(CostAdjustProductEnum.ADJUST_AMOUNT.getAttr(), adjustAmount.negate());
            productArray.add(data);
            updateProductMap.put(productId, productStockUpdateEntity);
        }

        // 删除本次调整单和调整成本的数据
        costAdjustModel.deleteById(dataId, corpid);
        costAdjustProductModel.deleteByCostAdjustId(dataId, corpid);
        // 更新产品
        saveProduct(productArray,corpid,null,null,false);
        //发送重算信息
        CostRecalculationDTO costRecalculationDTO = new CostRecalculationDTO();
        List<Long> costAdjustIdList = new ArrayList<>();
        costAdjustIdList.add(dataId);
        costRecalculationDTO.setCorpid(corpid);
        costRecalculationDTO.setType(StockTypeEnum.ADJUST_STOCK.getCode());
        costRecalculationDTO.setMark(BasicConstant.TWO);
        costRecalculationDTO.setIsWorkFlow(BasicConstant.ONE);
        costRecalculationDTO.setStockIdIn(costAdjustIdList);
        costRecalculationDTO.setBatchOutStockIdIn(Collections.singletonList(dataId));
        costRecalculationDTO.setStockFlowBillUpdateList(stockFlowBillUpdateList);
        costRecalculationDTO.setBatchFlowBillUpdateEntityList(batchFlowBillUpdateEntityList);
        /*stockFlowBillService.caculateStockModification4Delete(Collections.singletonList(dataId), stockFlowBillUpdateList, XbbRefTypeEnum.COST_ADJUST.getCode(), corpid);
        batchFlowBillService.batchFlowModification4Delete(Collections.singletonList(dataId), batchFlowBillUpdateEntityList, XbbRefTypeEnum.COST_ADJUST.getCode(), corpid);*/
        CostAdjustDeleteBatchVO deleteBatchVO = new CostAdjustDeleteBatchVO();
        deleteBatchVO.setDeleteIds(Collections.singletonList(dataId));
        costRecalculationProducer.sendMessage(costRecalculationDTO);
        return deleteBatchVO;
    }

    /**
     * 批量编辑某个字段
     *
     * @param attrUpdateDTO 编辑的字段信息
     * @throws XbbException 异常
     */
    @Override
    public void batchEditAttr(CostAdjustEditAttrUpdateDTO attrUpdateDTO) throws XbbException {
        try {
            // 将编辑的字段信息转换为成本调整单修改实体
            List<CostAdjustUpdateDTO> costAdjustUpdateList = attrUpdateDTO.getDataIdList().stream().map(item -> {
                CostAdjustUpdateDTO outstockUpdateDTO = new CostAdjustUpdateDTO();
                outstockUpdateDTO.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(attrUpdateDTO.getFieldEditedList());
                outstockUpdateDTO.setData(data);
                return outstockUpdateDTO;
            }).collect(Collectors.toList());
            // 修改成本调整单信息
            List<CostAdjustEntityExt> entityExtList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionsUtil.isNotEmpty(costAdjustUpdateList)) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid", attrUpdateDTO.getCorpid());
                param.put("idIn", attrUpdateDTO.getDataIdList());
                entityExtList = costAdjustModel.findEntitys(param);
                if (Objects.isNull(entityExtList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                CostAdjustUpdateBatchDTO costAdjustUpdateBatchDTO = new CostAdjustUpdateBatchDTO();
                BeanUtil.copyProperties(attrUpdateDTO, costAdjustUpdateBatchDTO);
                costAdjustUpdateBatchDTO.setCostAdjustList(costAdjustUpdateList);
                updateBatch(costAdjustUpdateBatchDTO);
            }
            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (CostAdjustEntityExt item : entityExtList) {
                dataIdList.add(item.getId());
                String serialNo = item.getSerialNo();
                updataItemList.add(serialNo);
            }
            String updataItem = StringUtils.join(updataItemList, "，");
            String userId = attrUpdateDTO.getUserId();
            String corpid = attrUpdateDTO.getCorpid();
            String loginUserName = attrUpdateDTO.getLoginUserName();
            // 标签特殊处理
            Integer fieldType = attrUpdateDTO.getFieldType();
            Boolean isFieldDependence = attrUpdateDTO.getIsFieldDependence();
            logHelp.analysisLabel(corpid, fieldType, isFieldDependence, attrUpdateDTO.getLogFieldEditedList());

            String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(attrUpdateDTO.getLogFieldEditedList());
            if (dataIdList.size() > 1) {
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.COST_ADJUST.getName(),
                        changedLogItemsStr, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.COST_ADJUST.getName());
                infoArrPojo.setContent(updataItem);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.COST_ADJUST, OperateTypeEnum.EDIT,
                        "", "", memo, attrUpdateDTO.getHttpHeader());
            } else if (Objects.equals(dataIdList.size(), 1)) {
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.COST_ADJUST.getName(), updataItem,
                        changedLogItemsStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.COST_ADJUST, OperateTypeEnum.EDIT,
                        dataIdList.get(0).toString(), updataItem, memo, attrUpdateDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("costAdjustService.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 批量更新
     *
     * @param updateBatchDTO 修改实体
     * @throws XbbException 异常
     */
    @Override
    public void updateBatch(CostAdjustUpdateBatchDTO updateBatchDTO) throws XbbException {
        try {
            String corpid = updateBatchDTO.getCorpid();
            List<UpdateDataEntity> updateDataList = updateBatchDTO.getCostAdjustList().stream().map(item -> ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid)).collect(Collectors.toList());
            if (CollectionsUtil.isNotEmpty(updateDataList)) {
                costAdjustModel.updateBatch(updateDataList, corpid);
            }
        } catch (Exception e) {
            LOG.error("costAdjustService.updateBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 将Excel数据格式化成表单保存需要的JSON格式的数据
     *
     * @param importFormDataDTO 导入入参
     * @param titlePojoList     标题
     * @param rowGroupPojo      一个表单对应的一组Excel填写的数据
     * @param fieldAttrList     解释
     * @return FormDataAddDTO
     * @throws XbbException XbbException
     */
    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        String corpid = importFormDataDTO.getCorpid();
        Integer businessType = importFormDataDTO.getBusinessType();
        // data 数据
        JSONObject dataJson = new JSONObject();

        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);
        // 遍历数据
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            String attr = fieldAttrEntityForImport.getAttr();
            Integer fieldType = fieldAttrEntityForImport.getFieldType();
            String attrName = fieldAttrEntityForImport.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);

            if (Objects.equals(attr, CostAdjustEnum.PRODUCT.getAttr())) {
                importHelper.formatCommonProduct(titlePojoList, dataJson, rowValueList, fieldAttrEntityForImport, businessType, corpid);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType())) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttrEntityForImport, dataJson);
            } else if (Objects.equals(attr, CostAdjustEnum.OWNER_ID.getAttr())) {
                importHelper.formatOwnId4Import(formDataAddDTO, fieldAttrEntityForImport, cellValue);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200022);
                }
                formDataAddDTO.setSerialNo(cellValue.toString());
            } else if (Objects.equals(attr, CostAdjustEnum.ADJUST_TIME.getAttr())) {
                Long time = DateTimeUtil.getExcelTime(cellValue.toString());
                if (time == 0L) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.FORMAT_INVALID, fieldAttrEntityForImport.getAttrName());
                }
                SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
                //校验日期是否受结账限制
                if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
                    if (time <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                        throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212035);
                    }
                }
                dataJson.put(attr, time);
            } else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttrEntityForImport.getFieldType())) {
                    importHelper.formatCommonField(dataJson, fieldAttrEntityForImport, cellValue);
                } else {
                    dataJson.put(attr, cellValue);
                }
            }
        }
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    /**
     * 格式化导出值
     *
     * @param paasFormDataESList 数据
     * @param formDataListDTO
     * @param fieldAttrList
     * @throws XbbException 异常
     */
    @Override
    public void formatExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        // 所有产品map
        List<Long> idList = paasFormDataESList.stream().map(PaasFormDataEntityExt::getDataId).collect(Collectors.toList());
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        List<ProductEntityExt> productList = productModel.findEntitys(params);
        Map<Long, ProductEntityExt> productMap = productList.stream().collect(Collectors.toMap(ProductEntityExt::getId, item -> item));
        // 入库关联产品map
        params.put("costAdjustIdIn", idList);
        params.put("orderByStr", "sort");
        List<CostAdjustProductEntity> costAdjustProductEntityList = costAdjustProductModel.findEntitys(params);
        Map<Long, List<CostAdjustProductEntity>> costAdjustProductMap = new HashMap<>();
        for (CostAdjustProductEntity productEntity : costAdjustProductEntityList) {
            Long costAdjustId = productEntity.getCostAdjustId();
            List<CostAdjustProductEntity> costAdjustProductEntitys = costAdjustProductMap.getOrDefault(costAdjustId, new ArrayList<>());
            costAdjustProductEntitys.add(productEntity);
            costAdjustProductMap.put(costAdjustId, costAdjustProductEntitys);
        }
        // 所有仓库map
        params.remove("costAdjustIdIn");
        params.remove("orderByStr");
        List<WarehouseEntityExt> warehouseList = warehouseModel.findEntitys(params);
        Map<Long, WarehouseEntityExt> warehouseMap = warehouseList.stream().collect(Collectors.toMap(WarehouseEntityExt::getId, item -> item));
        // 产品，库存产品
        FieldAttrEntityForImport productFieldAttr = new FieldAttrEntityForImport();
        for (FieldAttrEntityForImport item : fieldAttrList) {
            if (Objects.equals(item.getAttr(), CostAdjustEnum.PRODUCT.getAttr())) {
                productFieldAttr = item;
            }
        }
        // 精度
        SubFormPoJo subFormPoJo = productFieldAttr.getSubForm();
        FieldAttrEntity costFieldAttrEntity = new FieldAttrEntity();
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        handlerExplainDTO.setLoginUser(formDataListDTO.getLoginUser());
        handlerExplainDTO.setUserId(formDataListDTO.getUserId());

        Map<String, MultiUnitItemPoJo> groupBaseUnitStringMap = relativeProductHelp.getGroupBaseUnitStringMap(formDataListDTO.getCorpid());
        // 暂时只处理产品
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            JSONObject formDataObj = paasFormDataEntityExt.getData();
            String productAttr = productFieldAttr.getAttr();
            Long dataId = paasFormDataEntityExt.getDataId();
            handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
            handlerExplainDTO.setOwnerId(Collections.singletonList(paasFormDataEntityExt.getOwnerId()));
            List<CostAdjustProductEntity> costAdjustProductEntities = costAdjustProductMap.get(dataId);
            if (CollectionsUtil.isEmpty(costAdjustProductEntities)) {
                formDataObj.put(productAttr, new JSONArray());
                continue;
            }
            JSONArray productArray = new JSONArray();
            for (CostAdjustProductEntity productEntity : costAdjustProductEntities) {
                Long productId = productEntity.getProductId();
                Long warehouseId = productEntity.getWarehouseId();
                // 产品信息转换
                JSONObject productObj = new JSONObject();
                importHelper.formatProduct4Export(productMap, warehouseMap, productId, 0D, warehouseId, productObj);
                productObj.put(CostAdjustProductEnum.ADJUST_AMOUNT.getAttr(), productEntity.getCostAdjustAmount());
                productObj.put(CostAdjustProductEnum.BATCH.getAttr(), productEntity.getBatch());
                Long guaranteePeriod = productEntity.getGuaranteePeriod();
                if (productEntity.getGuaranteePeriod() != null) {
                    Long guaranteePeriodDay = guaranteePeriod / 86400;
                    if (!Objects.equals(guaranteePeriodDay, 0L)) {
                        productObj.put(SelectProductEnum.GUARANTEE_PERIOD.getAttr(), guaranteePeriodDay);
                    }else {
                        productObj.put(SelectProductEnum.GUARANTEE_PERIOD.getAttr(), 0);
                    }
                }
                Long produceDate = productEntity.getProduceDate();
                if (produceDate == null || produceDate == 0L) {
                    productObj.put(SelectProductEnum.PRODUCE_DATE.getAttr(), "");
                    productObj.remove(SelectProductEnum.GUARANTEE_PERIOD.getAttr());
                } else {
                    String produceDateStr = DateTimeUtil.getStringEpochSecond(produceDate, DateTimeUtil.SDFDate);
                    productObj.put(SelectProductEnum.PRODUCE_DATE.getAttr(), produceDateStr);
                    productObj.put(SelectProductEnum.EXPIRE_DATE.getAttr(), DateTimeUtil.getStringEpochSecond(produceDate + guaranteePeriod, DateTimeUtil.SDFDate));
                }
                //基本单位时直接塞入productUnit
                if (Objects.nonNull(productEntity.getProductUnit())) {
                    if (Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)) {
                        productObj.put(ProductEnum.UNIT.getAttr(), groupBaseUnitStringMap.getOrDefault(productEntity.getGroupId().toString(), new MultiUnitItemPoJo()).getBaseName());
                        productEntity.setProductUnit(productObj.getString(ProductEnum.UNIT.getAttr()));
                    }
                }
                productArray.add(productObj);
            }
            formDataObj.put(productAttr, productArray);
        }
    }

    @Override
    public CostAdjustEntityExt getEntityById(Long dataId , String corpid) throws XbbException{
        return costAdjustModel.getByKey(dataId , corpid);
    }
    /**
     * 关联新建时格式化解释
     *
     * @param handlerExplainInLinkItemDTO 关联新建表单解释的参数dto
     * @throws XbbException 异常
     */
    @Override
    public void formatLinkAddExplain(HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        // 关联BusinessType
        Integer linkBusinessType = handlerExplainInLinkItemDTO.getLinkBusinessType();
        try {
            handlerExplainInLinkItemDTO.setBusinessType(handlerExplainInLinkItemDTO.getPaasFormExplainEntity().getBusinessType());
            // 当来自产品详情的请求链接时
            if (Objects.equals(XbbRefTypeEnum.PRODUCT.getCode(), linkBusinessType)) {
                // 产品链接拼接解释
                this.productLinkJointExplain(handlerExplainInLinkItemDTO);
            }
        } catch (XbbException e){
            throw e;
        } catch (Exception e) {
            LOG.error("CostAdjustService.formatLinkAddExplain 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 工作流保存之后的操作
     *
     * @param saasFormSaveDTO 表单信息
     * @throws XbbException 异常
     */
    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        // 公司ID
        String corpid = saasFormSaveDTO.getCorpid();
        // 成本调整单信息
        PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        // 根据公司ID和数据ID查询del为0、6的成本调整单产品信息
        List<CostAdjustProductEntity> costAdjustProductList = costAdjustProductModel.listByAdjustId(corpid, newEntity.getDataId(), Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.APPROVE_FAILED.getDel()));
        // 获取成本调整单产品表ID
        Set<Long> removeCostAdjustProductIdSet = new HashSet<>();
        if (CollectionsUtil.isNotEmpty(costAdjustProductList)) {
            removeCostAdjustProductIdSet.addAll(costAdjustProductList.stream().map(CostAdjustProductEntity::getId).collect(Collectors.toSet()));
        }
        // 审批数据
        JSONObject data = saasFormSaveDTO.getNewData();
        // 审批的产品信息集合
        JSONArray productJsonArray = data.getJSONArray(InstockEnum.PRODUCT.getAttr());
        // 需要修改的成本调整单产品信息
        JSONArray updateCostAdjustList = new JSONArray();
        // 需要新增的成本调整单产品信息
        JSONArray addCostAdjustList = new JSONArray();
        for (int i = 0; i < productJsonArray.size(); i++) {
            // 产品信息
            JSONObject productJsonObject = productJsonArray.getJSONObject(i);
            // 成本调整单产品表ID
            Long costAdjustProductId = productJsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID);
            if (Objects.nonNull(costAdjustProductId)) {
                // 还存在的成本调整单产品表ID移除掉
                removeCostAdjustProductIdSet.remove(costAdjustProductId);
                updateCostAdjustList.add(productJsonObject);
            } else {
                addCostAdjustList.add(productJsonObject);
            }
        }
        // 成本调整单ID
        Long costAdjustId = newEntity.getId();
        // 表单ID
        Long formId = newEntity.getFormId();
        // 新增的成本调整单产品信息
        if (CollectionsUtil.isNotEmpty(addCostAdjustList)) {
            saveProduct(addCostAdjustList, corpid, costAdjustId, formId,true);
        }
        // 更新成本调整单产品信息
        batchUpdateCostAdjust(updateCostAdjustList, corpid, costAdjustId, formId);
        // 删除成本信息
        costAdjustProductModel.deleteBatchById(removeCostAdjustProductIdSet, corpid, DelEnum.DELETE.getDel());
    }

    /**
     * 获取仓库ID
     *
     * @param jsonArray 仓库信息
     * @return 仓库ID
     * @throws XbbException 异常
     */
    private Long getWarehouseId(JSONArray jsonArray) throws XbbException {
        if (CollectionsUtil.isEmpty(jsonArray)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, MessageConstant.WAREHOUSE_INFO_NOT_EMPTY);
        }
        JSONObject warehouseInfo = jsonArray.getJSONObject(0);
        if (MapUtils.isEmpty(warehouseInfo)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, MessageConstant.WAREHOUSE_INFO_NOT_EMPTY);
        }
        String warehouseName = warehouseInfo.getString("name");
        Long warehouseId = warehouseInfo.getLong("id");
        if (Objects.isNull(warehouseId)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, MessageConstant.WAREHOUSE_INFO_NOT_EMPTY, warehouseName);
        }
        return warehouseId;
    }

    /**
     * 找到产品的所有仓库信息
     *
     * @param corpid      公司ID
     * @param productList 产品信息集合
     * @return 仓库信息 map -> 产品ID value -> 产品的所有仓库信息
     * @throws XbbException 异常
     */
    private Map<Long, List<ProductWarehouseEntity>> findProductAllWarehouse(String corpid, JSONArray productList) throws XbbException {
        if (CollectionsUtil.isEmpty(productList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, MessageConstant.PRODUCT_INFO_NOT_EMPTY);
        }
        List<Long> productIdList = this.getProductIdList(productList);
        List<ProductWarehouseEntity> productWarehouseList = productWarehouseModel.getIdList(corpid, productIdList);
        Map<Long, List<ProductWarehouseEntity>> productWarehouseMap = new HashMap<>();
        for (ProductWarehouseEntity entity : productWarehouseList) {
            Long productId = entity.getProductId();
            List<ProductWarehouseEntity> value = productWarehouseMap.getOrDefault(productId, new ArrayList<>());
            value.add(entity);
            productWarehouseMap.put(productId, value);
        }
        return productWarehouseMap;
    }

    /**
     * 找到存在批次的产品
     *
     * @param corpid      公司ID
     * @param productList 产品ID集合
     * @return 产品批次信息
     * @throws XbbException 异常
     */
    private Map<Long, List<ProductStockEntity>> findProductAllBatch(String corpid, JSONArray productList) throws XbbException {
        if (CollectionsUtil.isEmpty(productList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, MessageConstant.PRODUCT_INFO_NOT_EMPTY);
        }
        List<Long> productIdList = this.getProductIdList(productList);
        List<Long> warehouseIdList = new ArrayList<>();
        for (int i = 0; i < productList.size(); i++) {
            JSONObject productJson = productList.getJSONObject(i);
            warehouseIdList.add(this.getWarehouseId(productJson.getJSONArray(CostAdjustProductEnum.WAREHOUSE.getAttr())));
        }
        List<ProductStockEntity> productStockEntityList = productStockModel.listByProductIdIn(corpid, productIdList, warehouseIdList);
        Map<Long, List<ProductStockEntity>> productStockMap = new HashMap<>();
        for (ProductStockEntity productStockEntity : productStockEntityList) {
            Long productId = productStockEntity.getProductId();
            List<ProductStockEntity> productStockList = productStockMap.getOrDefault(productId, new ArrayList<>());
            productStockList.add(productStockEntity);
            productStockMap.put(productId, productStockList);
        }
        return productStockMap;
    }

    /**
     * 获取产品ID集合
     *
     * @param productList 产品信息
     * @return 产品ID集合
     * @throws XbbException 异常
     */
    private List<Long> getProductIdList(JSONArray productList) throws XbbException {
        List<Long> productIdList = new ArrayList<>(productList.size());
        for (int i = 0; i < productList.size(); i++) {
            JSONObject products = productList.getJSONObject(i);
            Long productId = products.getLong(CostAdjustProductEnum.PRODUCT.getAttr());
            if (Objects.isNull(productId)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, MessageConstant.PRODUCT_INFO_NOT_EMPTY);
            }
            productIdList.add(productId);
        }
        return productIdList;
    }

    /**
     * 获取批次总成本
     *
     * @param productStockEntityList 产品批次信息
     * @param jsonObject             产品信息
     * @param adjustAmount           调整金额
     * @return 批次总成本
     */
    private BigDecimal getBatchTotalCost(List<ProductStockEntity> productStockEntityList, List<ProductStockUpdateEntity> updateStockList, JSONObject jsonObject, BigDecimal adjustAmount) throws XbbException {
        BigDecimal totalBatchAmount = BigDecimal.ZERO;
        if (!Objects.equals(jsonObject.getInteger(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getSaasAttr()), 1) || CollectionsUtil.isEmpty(productStockEntityList)) {
            return totalBatchAmount;
        }
        Long productId = jsonObject.getLong(CostAdjustProductEnum.PRODUCT.getAttr());
        Long warehouseId = this.getWarehouseId(jsonObject.getJSONArray(CostAdjustProductEnum.WAREHOUSE.getAttr()));
        String batchKey = BatchKeyHelp.getBatchKey(productId, warehouseId, jsonObject.getString(CostAdjustProductEnum.BATCH.getAttr()),
                jsonObject.getLong(CostAdjustProductEnum.PRODUCE_DATE.getAttr()), getGuaranteePeriod(jsonObject.getLong(CostAdjustProductEnum.GUARANTEE_PERIOD.getAttr())));
        for (ProductStockEntity stockEntity : productStockEntityList) {
            BigDecimal totalCost = BigDecimal.valueOf(Objects.isNull(stockEntity.getTotalCost()) ? 0D : stockEntity.getTotalCost());
            if (Objects.equals(batchKey, stockEntity.getBatchKey())) {
                totalCost = totalCost.add(adjustAmount);
                stockEntity.setTotalCost(totalCost.doubleValue());
                double cost = 0D;
                if (!Objects.equals(BigDecimal.ZERO, totalCost)) {
                    cost = totalCost.divide(BigDecimal.valueOf(stockEntity.getNum()), 7, RoundingMode.HALF_DOWN).doubleValue();
                }
                stockEntity.setCost(cost);
                ProductStockUpdateEntity stockUpdateEntity = new ProductStockUpdateEntity(stockEntity.getProductId(), adjustAmount.doubleValue());
                stockUpdateEntity.setKey(stockEntity.getBatchKey());
                updateStockList.add(stockUpdateEntity);
                jsonObject.put(BusinessConstant.ADJUST_BATCH_STOCK, stockEntity.getNum());
                jsonObject.put(BusinessConstant.ADJUST_BATCH_COST, stockEntity.getCost());
                jsonObject.put(BusinessConstant.ADJUST_AMOUNT, adjustAmount);
            }
            totalBatchAmount = totalBatchAmount.add(totalCost);
        }
        return totalBatchAmount;
    }

    /**
     * 获取仓库总成本
     *
     * @param productWarehouseList 产品仓库信息
     * @param totalBatchAmount     批次总成本
     * @param adjustAmount         调整金额
     * @return 批次总成本
     */
    private BigDecimal getWarehouseTotalCost(List<ProductWarehouseEntity> productWarehouseList, List<ProductWarehouseEntity> updateWarehouseList, JSONObject jsonObject,
                                             Long productId, Long warehouseId, BigDecimal totalBatchAmount, BigDecimal adjustAmount) {
        BigDecimal totalWarehouseAmount = BigDecimal.ZERO;
        Integer enableBatchShelfLife = jsonObject.getInteger(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr());
        for (ProductWarehouseEntity warehouseEntity : productWarehouseList) {
            BigDecimal totalCost = BigDecimal.valueOf(Objects.isNull(warehouseEntity.getTotalCost()) ? 0D : warehouseEntity.getTotalCost());
            if (Objects.equals(warehouseEntity.getProductId(), productId) && Objects.equals(warehouseEntity.getWarehouseId(), warehouseId)) {
                totalCost = Objects.equals(enableBatchShelfLife, 1) ?  totalBatchAmount: totalCost.add(adjustAmount);
                warehouseEntity.setTotalCost(totalCost.doubleValue());
                double cost = 0D;
                if (!Objects.equals(BigDecimal.ZERO, totalCost) && !Objects.equals(warehouseEntity.getNum(), 0D)) {
                    cost = totalCost.divide(BigDecimal.valueOf(warehouseEntity.getNum()), 7, RoundingMode.HALF_DOWN).doubleValue();
                }
                if (!Objects.equals(warehouseEntity.getNum(), 0D)) {
                    warehouseEntity.setCost(cost);
                }
                updateWarehouseList.add(warehouseEntity);
                jsonObject.put(BusinessConstant.ADJUST_WAREHOUSE_STOCK, warehouseEntity.getNum());
                jsonObject.put(BusinessConstant.ADJUST_WAREHOUSE_COST, warehouseEntity.getCost());
                jsonObject.put(BusinessConstant.ADJUST_AMOUNT, adjustAmount);
            }
            totalWarehouseAmount = totalWarehouseAmount.add(totalCost);
        }
        return totalWarehouseAmount;
    }

    /**
     * 获取调整单实体
     *
     * @param adjustAmount                调整
     * @param batchKey                    批次
     * @param productData                 产品信息
     * @param productStockEntityList      产品批次信息
     * @param productWarehouseEntitieList 产品仓库信息
     * @return 调整单实体
     */
    private CostAdjustProductEntity getAdjustEntity(BigDecimal adjustAmount, String batchKey, JSONObject productData, Long productId, Long warehouseId,
                                                    List<ProductStockEntity> productStockEntityList, List<ProductWarehouseEntity> productWarehouseEntitieList) {
        CostAdjustProductEntity costAdjustProductEntity = new CostAdjustProductEntity();
        int now = DateUtil.getInt();
        BigDecimal num;
        BigDecimal newCost;
        BigDecimal totalCost;
        BigDecimal oldCost;
        String batch = "";
        ProductStockEntity productStockEntity = null;
        Integer enableBatchShelfLife = productData.getInteger(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr());
        // 判断产品是否存在批次
        if (CollectionsUtil.isNotEmpty(productStockEntityList) && Objects.equals(enableBatchShelfLife, 1)) {
            productStockEntity = productStockEntityList.stream().filter(entity -> Objects.equals(entity.getBatchKey(), batchKey)).findFirst().orElse(null);
        }
        if (Objects.nonNull(productStockEntity)) {
            costAdjustProductEntity.setProduceDate(productStockEntity.getProduceDate());
            costAdjustProductEntity.setGuaranteePeriod(productStockEntity.getGuaranteePeriod());
            num = BigDecimal.valueOf(productStockEntity.getNum());
            newCost = BigDecimal.valueOf(productStockEntity.getCost());
            totalCost = BigDecimal.valueOf(productStockEntity.getTotalCost());
            if (!Objects.equals(num, new BigDecimal("0.0"))) {
                oldCost = totalCost.subtract(adjustAmount).divide(num, 7, RoundingMode.HALF_DOWN);
            } else {
                oldCost = BigDecimal.ZERO;
            }
            batch = productStockEntity.getBatch();
        } else {
            ProductWarehouseEntity productWarehouseEntity = productWarehouseEntitieList.stream().filter(entity -> Objects.equals(entity.getProductId(), productId) && Objects.equals(entity.getWarehouseId(), warehouseId)).findFirst().orElse(new ProductWarehouseEntity());
            num = BigDecimal.valueOf(productWarehouseEntity.getNum());
            newCost = BigDecimal.valueOf(productWarehouseEntity.getCost());
            totalCost = BigDecimal.valueOf(productWarehouseEntity.getTotalCost());
            if (!Objects.equals(num, new BigDecimal("0.0"))) {
                oldCost = totalCost.subtract(adjustAmount).divide(num, 7, RoundingMode.HALF_DOWN);
            } else {
                oldCost = BigDecimal.ZERO;
            }
        }
        costAdjustProductEntity.setInventoryNumber(num);
        costAdjustProductEntity.setOldCost(oldCost);
        costAdjustProductEntity.setNewCost(newCost);
        costAdjustProductEntity.setTotalCost(totalCost);
        costAdjustProductEntity.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
        costAdjustProductEntity.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
        costAdjustProductEntity.setProductPicture(productData.getString(ProductEnum.PRODUCT_IMGS.getAttr()));
        costAdjustProductEntity.setProductNo(productData.getString(ProductEnum.PRODUCT_NO.getAttr()));
        costAdjustProductEntity.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION.getAttr()));
        costAdjustProductEntity.setBatch(batch);
        costAdjustProductEntity.setAddTime(now);
        costAdjustProductEntity.setUpdateTime(now);
        costAdjustProductEntity.setDel(0);
        return costAdjustProductEntity;
    }

    /**
     * @param corpid
     * @param groupId 多单位产品组id
     * @return
     * @throws XbbException
     */
    private Map<String, String> getUnitMap4Product(String corpid, Long groupId) throws XbbException {
        Map<String, String> unitMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        ProductFieldPojo productFieldPojo = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), corpid);
        //单单位
        if (Objects.isNull(groupId) || Objects.equals(groupId, 0L)) {
            List<ItemPoJo> singleItems = productFieldPojo.getSingleItems();
            singleItems.forEach(item -> unitMap.put(item.getValue().toString(), item.getText()));
            return unitMap;
        }
        //多单位
        List<MultiUnitItemPoJo> multiItems = productFieldPojo.getMultiItems();
        multiItems.forEach(item -> unitMap.put(item.getBaseValue().toString(), item.getBaseName()));
        return unitMap;
    }


    public DetailProductVO formatProduct4DetailShow(List<CostAdjustProductEntity> productEntityList, PagingProductDTO pagingProductDTO) throws XbbException {
        DetailProductVO detailProductVO = new DetailProductVO();
        List<Long> warehouseIdList = productEntityList.stream().map(CostAdjustProductEntity::getWarehouseId).collect(Collectors.toList());
        List<PaasFormDataEntityExt> warehouseList = paasEsModel.getByIdList(warehouseIdList, pagingProductDTO.getCorpid(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WAREHOUSE.getCode(), new ArrayList<>(), IndexTypeEnum.IDX_SAAS_WAREHOUSE);
        Map<Long, String> warehouseNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt paasFormDataEntityExt : warehouseList) {
            JSONObject data = paasFormDataEntityExt.getData();
            warehouseNameMap.put(paasFormDataEntityExt.getId(), FastJsonHelper.getStringOrDefaultFromFormData(data, WarehouseEnum.WAREHOUSE_NAME.getAttr(), ""));
        }
        JSONArray productArray = new JSONArray();
        for (CostAdjustProductEntity productEntity : productEntityList) {
            JSONObject json = Objects.isNull(productEntity.getData()) ? new JSONObject() : productEntity.getData();
            for (CostAdjustProductEnum productEnum : CostAdjustProductEnum.values()) {
                String attr = productEnum.getAttr();
                switch (productEnum) {
                    case PRODUCT:
                        json.put(attr, productEntity.getProductId());
                        break;
                    case WAREHOUSE:
                        JSONArray warehouseArr = productHelp.packegeLinkBusinessJsonArray(productEntity.getWarehouseId(),
                                warehouseNameMap.getOrDefault(productEntity.getWarehouseId(), ""), XbbRefTypeEnum.WAREHOUSE.getCode(), SaasMarkEnum.SAAS.getCode());
                        json.put(attr, warehouseArr);
                        break;
                    case OLD_COST:
                        json.put(attr, productEntity.getOldCost());
                        break;
                    case NEW_COST:
                        json.put(attr, productEntity.getNewCost());
                        break;
                    case ADJUST_AMOUNT:
                        json.put(attr, productEntity.getCostAdjustAmount());
                        break;
                    case TOTAL_COST:
                        json.put(attr, productEntity.getTotalCost());
                        break;
                    case STOCK:
                        json.put(attr, productEntity.getInventoryNumber());
                        break;
                    case BATCH:
                        json.put(attr, productEntity.getBatch());
                        break;
                    case BASIC_UNIT:
                        json.put(attr, productEntity.getProductUnit());
                        break;
                    case PRODUCE_DATE:
                        json.put(attr, productEntity.getProduceDate());
                        break;
                    case GUARANTEE_PERIOD:
                        json.put(attr, productEntity.getGuaranteePeriod());
                        break;
                    default:
                        break;
                }
            }
            json.put("refId", productEntity.getId());
            json.put(SelectProductEnum.UNIT_GROUP.getAttr(), productEntity.getGroupId());
            json.put(SelectProductEnum.RATE.getAttr(), productEntity.getRate());
            json.put(SelectProductEnum.BUSINESS_UNIT.getAttr(), productEntity.getBusinessUnit());
            json.put(BusinessConstant.PRODUCT_SUB_ID, productEntity.getId());
            productArray.add(json);
        }
        detailProductVO.setProductDataArr(productArray);
        return detailProductVO;
    }

    /**
     * 删除检查
     *
     * @param costAdjustDeleteBatchDTO 删除的条件
     */
    private CostAdjustEntityExt deletecheck(CostAdjustDeleteBatchDTO costAdjustDeleteBatchDTO) throws XbbException {
        // 公司ID
        String corpid = costAdjustDeleteBatchDTO.getCorpid();
        // 成本调整单不支持批量删除
        List<Long> dataIdList = costAdjustDeleteBatchDTO.getDataIdList();
        if (CollectionsUtil.isEmpty(dataIdList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        if (dataIdList.size() > 1) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002, MessageConstant.ADJUST_BATCH_DELETION_NOT_SUPPORTED);
        }
        Long dataId = dataIdList.get(0);
        CostAdjustEntityExt costAdjustEntityExt = costAdjustModel.getByKey(dataId, corpid);
        if (Objects.isNull(costAdjustEntityExt) || Objects.isNull(costAdjustEntityExt.getData())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100002);
        }
        JSONObject data = costAdjustEntityExt.getData();
        // 删除的调整单不得小于最后一次结账日期
        SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
        Long adjustTime = data.getLong(CostAdjustEnum.ADJUST_TIME.getAttr());
        if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
            if (adjustTime < DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212080);
            }
        }
        return costAdjustEntityExt;

    }

    private void batchUpdateCostAdjust(JSONArray productArray, String corpid, Long costAdjustId, Long formId) throws XbbException {
        //新增
        List<CostAdjustProductEntity> updateCostAdjustProductEntityList = new ArrayList<>();
        // 获取调整单产品信息
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid, productArray);
        // 获取调整单产品所有仓库信息
        Map<Long, List<ProductWarehouseEntity>> productAllWarehouseMap = this.findProductAllWarehouse(corpid, productArray);
        // 获取调整单产品所有批次信息
        Map<Long, List<ProductStockEntity>> productAllBatchMap = this.findProductAllBatch(corpid, productArray);
        // 需要跟新的产品信息
        Map<Long, ProductStockUpdateEntity> updateProductMap = new HashMap<>();
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            jsonObject.put(SelectProductEnum.NUM.getAttr(), 0);
            // 移除序列号相关数据，不存入关联产品数据中
            ProductFieldPojo productFieldPojo = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), corpid);
            // 产品ID
            Long productId = jsonObject.getLong(CostAdjustProductEnum.PRODUCT.getAttr());
            // 仓库ID
            Long warehouseId = this.getWarehouseId(jsonObject.getJSONArray(CostAdjustProductEnum.WAREHOUSE.getAttr()));
            // 批次Key
            String batchKey = BatchKeyHelp.getBatchKey(productId, warehouseId, jsonObject.getString(CostAdjustProductEnum.BATCH.getAttr()),
                    jsonObject.getLong(CostAdjustProductEnum.PRODUCE_DATE.getAttr()), getGuaranteePeriod(jsonObject.getLong(CostAdjustProductEnum.GUARANTEE_PERIOD.getAttr())));
            // 产品信息
            JSONObject productData = productMap.get(productId).getData();
            // 调整金额
            BigDecimal adjustAmount = jsonObject.getBigDecimal(CostAdjustProductEnum.ADJUST_AMOUNT.getAttr());
            // 获取批次总成本
            List<ProductStockEntity> productStockEntityList = productAllBatchMap.get(productId);
            // 获取仓库总成本
            List<ProductWarehouseEntity> productWarehouseEntitieList = productAllWarehouseMap.get(productId);
            if (CollectionsUtil.isEmpty(productWarehouseEntitieList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100018, MessageConstant.WAREHOUSE_INFO_NOT_EMPTY, productId);
            }
            if (Objects.isNull(adjustAmount)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
            }
            ProductStockUpdateEntity productStockUpdateEntity = new ProductStockUpdateEntity(productId,  Double.valueOf(adjustAmount.toString()));
            if (updateProductMap.containsKey(productId)) {
                ProductStockUpdateEntity updateEntity = updateProductMap.get(productId);
                Double cost = updateEntity.getCost();
                updateEntity.setCost(Double.valueOf(BigDecimal.valueOf(cost).add(adjustAmount).toString()));
            } else {
                updateProductMap.put(productId, productStockUpdateEntity);
            }
            // 获取调整单实体
            CostAdjustProductEntity costAdjustProductEntity = this.getAdjustEntity(adjustAmount, batchKey, productData, productId, warehouseId, productStockEntityList, productWarehouseEntitieList);
            costAdjustProductEntity.setId(jsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID));
            costAdjustProductEntity.setCorpid(corpid);
            costAdjustProductEntity.setFormId(formId);
            costAdjustProductEntity.setCostAdjustId(costAdjustId);
            costAdjustProductEntity.setProductId(productId);
            costAdjustProductEntity.setWarehouseId(warehouseId);
            costAdjustProductEntity.setSort(i);
            costAdjustProductEntity.setCostAdjustAmount(adjustAmount);
            String unitId = jsonObject.getString(CostAdjustProductEnum.BASIC_UNIT.getAttr());
            costAdjustProductEntity.setProductUnit(unitId);
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.nonNull(enableMultiUnit) && Objects.equals(enableMultiUnit, 1)) {
                List<MultiUnitItemPoJo> multiItems = productFieldPojo.getMultiItems();
                MultiUnitItemPoJo multiUnitItemPoJo = null;
                if (CollectionUtils.isNotEmpty(multiItems)) {
                    multiUnitItemPoJo = multiItems.stream().filter(item -> Objects.equals(unitId, String.valueOf(item.getValue()))).findFirst().orElse(null);
                }
                if (Objects.nonNull(multiUnitItemPoJo)) {
                    costAdjustProductEntity.setBusinessUnit(multiUnitItemPoJo.getBaseValue());
                    List<UnitItemPoJo> itemDataPoJoList = multiUnitItemPoJo.getItemDataPoJoList();
                    MultiUnitItemPoJo finalMultiUnitItemPoJo = multiUnitItemPoJo;
                    UnitItemPoJo unitItemPoJo = itemDataPoJoList.stream().filter(item -> Objects.equals(finalMultiUnitItemPoJo.getBaseValue(), item.getValue())).findFirst().orElse(new UnitItemPoJo());
                    costAdjustProductEntity.setRate(unitItemPoJo.getRate());
                    costAdjustProductEntity.setGroupId(multiUnitItemPoJo.getValue());
                    costAdjustProductEntity.setProductUnit(String.valueOf(multiUnitItemPoJo.getBaseValue()));
                }
            } else {
                jsonObject.put(CostAdjustProductEnum.BASIC_UNIT.getAttr(), productData.getString(ProductEnum.UNIT.getAttr()));
            }
            jsonObject.put(CostAdjustProductEnum.STOCK.getAttr(), costAdjustProductEntity.getInventoryNumber());
            jsonObject.put(CostAdjustProductEnum.TOTAL_COST.getAttr(), costAdjustProductEntity.getTotalCost());
            costAdjustProductEntity.setData(jsonObject);
            updateCostAdjustProductEntityList.add(costAdjustProductEntity);
        }
        if (CollectionsUtil.isNotEmpty(updateCostAdjustProductEntityList)) {
            costAdjustProductModel.updateBatch(updateCostAdjustProductEntityList, corpid);
        }
    }

    private Long getGuaranteePeriod(Long guaranteePeriod) {
        if (Objects.isNull(guaranteePeriod)) {
            return 0L;
        }
        return guaranteePeriod * 86400;
    }

    private Long roolbackGuaranteePeriod(Long guaranteePeriod) {
        if (Objects.isNull(guaranteePeriod)) {
            return 0L;
        }
        return guaranteePeriod / 86400;
    }

    /**
     * 产品链接拼接解释
     *
     * @param handlerExplainInLinkItemDTO 关联新建表单解释的参数dto
     * @throws XbbException xbb异常
     */
    private void productLinkJointExplain(HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        // 公司ID
        String corpid = handlerExplainInLinkItemDTO.getCorpid();
        // 关联数据ID
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        // 关联信息
        PaasFormDataEntityExt paasFormDataEntityExt = handlerExplainInLinkItemDTO.getPaasFormDataEntityExt();
        // 关联编号
        String serialNo = paasFormDataEntityExt.getSerialNo();
        // 产品单位信息
        ProductFieldPojo productUnitPojo = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_UNIT, ProductEnum.UNIT.getAttr(), corpid);
        // 产品信息集合
        JSONArray productList = new JSONArray();
        for (FieldAttrEntity fieldAttrEntity : handlerExplainInLinkItemDTO.getExplainList()) {
            if (Objects.equals(fieldAttrEntity.getAttr(), CostAdjustEnum.PRODUCT.getAttr())) {
                // 找到子产品信息
                List<PaasFormDataEntityExt> paasFormDataESList = this.findChildProductList(corpid, Collections.singletonList(linkDataId));
                // 分仓库存和成本
                List<Long> prodiuctIdList = paasFormDataESList.stream().map(PaasFormDataEntityExt::getId).collect(Collectors.toList());
                Map<Long,Map<String,JSONObject>> productMap = formDataValidateProductHelp.getWarehouseMap(prodiuctIdList, corpid);
                for (PaasFormDataEntityExt entity : paasFormDataESList) {
                    // 关联链接的产品json
                    JSONObject likedProductData = entity.getData();
                    // 成本调整单产品信息
                    JSONObject costAdjustProduct = new JSONObject();
                    // 拼接单位信息
                    this.joinUnitInfo(costAdjustProduct, likedProductData, productUnitPojo);
                    // 拼接产品信息
                    this.jsonProductInfo(costAdjustProduct, entity, productMap, serialNo);
                    productList.add(costAdjustProduct);
                }
                fieldAttrEntity.setDefaultAttr(saasUpdateHelp.setDefaultValue(productList));
            }
        }
    }

    /**
     * 根据父产品ID找到对应的子产品信息
     *
     * @param corpid          公司ID
     * @param parentProductId 父产品ID集合
     * @return 子产品信息集合
     * @throws XbbException xbb异常
     */
    private List<PaasFormDataEntityExt> findChildProductList(String corpid, List<Long> parentProductId) throws XbbException {
        ChildProductDTO childProductDTO = new ChildProductDTO();
        childProductDTO.setCorpid(corpid);
        childProductDTO.setParentProductId(parentProductId);
        PaasFormDataEsListVO childProductList = productService.getChildProductList(childProductDTO);
        if (Objects.isNull(childProductList) || CollectionsUtil.isEmpty(childProductList.getPaasFormDataESList())) {
            return new ArrayList<>();
        }
        return childProductList.getPaasFormDataESList();
    }

    /**
     * 拼接单位信息
     *
     * @param costAdjustProduct 产品信息
     * @param likedProductData  链接产品信息
     * @param productUnitPojo   单位信息
     */
    private void joinUnitInfo(JSONObject costAdjustProduct, JSONObject likedProductData, ProductFieldPojo productUnitPojo) {
        // 多单位所有信息集合
        List<UnitItemPoJo> transformUnitRate = new ArrayList<>();
        // 产品单位
        String nuit = likedProductData.getString(ProductEnum.UNIT.getAttr());
        // 基本单位
        JSONObject basicUnit = new JSONObject();
        // 是否开启多单位
        Integer enableMultiUnit = likedProductData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
        if (Objects.nonNull(enableMultiUnit) && Objects.equals(enableMultiUnit, 1)) {
            // 多规格信息
            List<MultiUnitItemPoJo> multiItems = productUnitPojo.getMultiItems();
            for (MultiUnitItemPoJo item : multiItems) {
                if (Objects.equals(item.getValue().toString(), nuit)) {
                    transformUnitRate = item.getItemDataPoJoList();
                    // 拼接基本单位信息
                    basicUnit.put(StringConstant.TEXT, item.getBaseName());
                    basicUnit.put(StringConstant.VALUE, item.getBaseValue());
                }
            }
        } else {
            List<ItemPoJo> singleItems = productUnitPojo.getSingleItems();
            for (ItemPoJo item : singleItems) {
                if (Objects.equals(item.getValue().toString(), nuit)) {
                    basicUnit.put(StringConstant.TEXT, item.getText());
                    basicUnit.put(StringConstant.VALUE, item.getValue());
                }
            }
        }
        // 拼接基本单位
        costAdjustProduct.put(CostAdjustProductEnum.BASIC_UNIT.getAttr(), basicUnit);
        // 拼接多单位信息
        costAdjustProduct.put(ProductConstant.TRANSFORM_UNIT_RATE, transformUnitRate);
        costAdjustProduct.put(ProductConstant.UNIT_RATE, transformUnitRate);

    }

    /**
     * 拼接产品信息
     *
     * @param costAdjustProduct 调整单产品信息
     * @param entity            产品信息
     * @param productMap        分仓库存和成本
     * @param entity            链接信息
     */
    private void jsonProductInfo(JSONObject costAdjustProduct, PaasFormDataEntityExt entity, Map<Long, Map<String, JSONObject>> productMap, String serialNo) {
        JSONObject likedProductData = entity.getData();
        // 产品的信息
        JSONObject productData = new JSONObject();
        // 产品的基本信息
        JSONObject productBaseInfo = new JSONObject();
        // 基本信息-产品名字
        productBaseInfo.put(CostAdjustProductEnum.PRODUCT.getAttr(), likedProductData.get(ProductEnum.NAME.getAttr()));
        // 基本信息-产品编号
        productBaseInfo.put(ProductEnum.SERIALNO.getSaasAttr(), serialNo);
        // 基本信息-产品规格
        String decodeSpec = formDataHelp.decodeSpec(likedProductData.getString(ProductEnum.SPECIFICATION.getAttr()), likedProductData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()), null);
        productBaseInfo.put(ProductEnum.SPECIFICATION.getAttr(), decodeSpec);
        // 基本信息-产品图片
        productBaseInfo.put(ProductEnum.PRODUCT_IMGS.getAttr(), likedProductData.getOrDefault(ProductEnum.PRODUCT_IMGS.getAttr(), new ArrayList<>()));
        // 拼接产品基本信息
        productData.put(BasicConstant.DATA, productBaseInfo);

        JSONObject productInfo = new JSONObject();
        // 拼接是否启用批次保质期
        productInfo.put(ProductConstant.Enable_Batch_Shelf_Life, likedProductData.get(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getAttr()));
        // 拼接是否启用序列号
        productInfo.put(ProductConstant.Enable_Serial_Number, likedProductData.get(ProductEnum.ENABLE_SERIAL_NUMBER.getAttr()));
        String shelfLifeDays = likedProductData.getString(ProductEnum.SHELF_LIFE_DAYS.getAttr());
        productInfo.put(ProductConstant.Shelf_Life_Days, StringUtil.isEmpty(shelfLifeDays) ? 0 : 1);
        // 拼接保质期天数
        productInfo.put(ProductEnum.SHELF_LIFE_DAYS.getAttr(), shelfLifeDays);
        productInfo.put(CostAdjustProductEnum.PRODUCE_DATE.getAttr(), DateUtil.getString(new Date(), DateUtil.SDFDate));
        productInfo.put(CostAdjustProductEnum.GUARANTEE_PERIOD.getAttr(), likedProductData.get(ProductEnum.SHELF_LIFE_DAYS.getAttr()));
        Map<String, JSONObject> warehouseMap = productMap.getOrDefault(entity.getId(), new HashMap<>());
        productInfo.put(StringConstant.WAREHOUSE, warehouseMap);
        productData.put(StringConstant.SOURCE_DATA, productInfo);
        // 拼接产品ID
        productData.put(BasicConstant.DATAID, entity.getId());
        productData.put(BasicConstant.ID, entity.getId());
        productData.putAll(productInfo);
        costAdjustProduct.put(CostAdjustProductEnum.PRODUCT.getAttr(), productData);
    }

}
